package com.pj.ca.util;

import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
import com.pj.ca.modal.SignInfo;

import java.io.ByteArrayOutputStream;


/**
 * 描述：
 *
 * @author pengjun
 * @date 2021/11/4 13:39
 */
public class PdfCertSignUtil {

public static byte[] sign( byte[] pdfByte, SignInfo signInfo) {
    ByteArrayOutputStream result = new ByteArrayOutputStream();
    doSign(result,pdfByte, signInfo);
    return result.toByteArray();
}

    private static void doSign(ByteArrayOutputStream result, byte[] pdfByte, SignInfo signInfo) {
        PdfReader reader = null;
        PdfStamper stamper = null;
        try {
            reader = new PdfReader(pdfByte);
            // 创建签章工具PdfStamper ，最后一个boolean参数是否允许被追加签名
            // false的话，pdf文件只允许被签名一次，多次签名，最后一次有效
            // true的话，pdf可以被追加签名，验签工具可以识别出每次签名之后文档是否被修改
            stamper = PdfStamper.createSignature(reader, result, '\0', null, true);
            // 获取数字签章属性对象
            PdfSignatureAppearance appearance = stamper
                    .getSignatureAppearance();
            appearance.setReason(signInfo.getReason());
            appearance.setLocation(signInfo.getLocation());
            // 设置签名的位置，页码，签名域名称，多次追加签名的时候，签名预名称不能一样 图片大小受表单域大小影响（过小导致压缩）
            // 签名的位置，是图章相对于pdf页面的位置坐标，原点为pdf页面左下角
            // 四个参数的分别是，图章左下角x，图章左下角y，图章右上角x，图章右上角y
            appearance.setVisibleSignature(
                    new Rectangle(signInfo.getRectllx(), signInfo
                            .getRectlly(), signInfo.getRecturx(),
                            signInfo.getRectury()), 1, signInfo
                            .getFieldName());
            // 读取图章图片
            Image image = Image.getInstance(signInfo.getSealChart());
            appearance.setSignatureGraphic(image);
            appearance.setCertificationLevel(signInfo
                    .getCertificationLevel());
            // 设置图章的显示方式，如下选择的是只显示图章（还有其他的模式，可以图章和签名描述一同显示）
            appearance.setRenderingMode(signInfo.getRenderingMode());
            // 摘要算法
            ExternalDigest digest = new BouncyCastleDigest();
            // 签名算法
            ExternalSignature signature = new PrivateKeySignature(
                    signInfo.getPk(), signInfo.getDigestAlgorithm(),
                    null);
            // 调用itext签名方法完成pdf签章 //数字签名格式，CMS,CADE
            MakeSignature.signDetached(appearance, digest, signature,
                    signInfo.getChain(), null, null, null, 0,
                    MakeSignature.CryptoStandard.CADES);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
